Creating a package

last modified

2023–10–17

How to create a package for pip

To create a distribution package, additional files beyond the implementation are needed. It is recommended to have a project directory named after the package, with implementation files and directories in a subdirectory src.

Modern Python packaging is based on a pyproject.toml file in the project directory.

Defining metadata

Metadata are provided in a TOML ‘table’ project:

[project]
  • Name of the distribution package. To avoid being changed by normalization, it should be lowercase and contain only az, 09, and -.

    name = "mkernel"
  • Version in the format of PEP 440. It can also be extracted from the implementation files, see below.

    version = "1.0.0"
  • A one-line description. Could include a different stylization of the package name.

    description = "MKernel: A Jupyter Kernel for Matlab"
  • Pointer to a README file in the same directory. Markdown (.md) and ReStructuredText (.rst) are automatically recognized.

    readme = "README.md"
  • Required version of Python. Should at least specify whether Python 2 or 3.

    requires-python = ">=3.3"
  • Names of authors. Emails can be specified with an additional key email.

    authors = [{name = "Carsten Allefeld"}]

    If separate from authors, there can be an additional entry maintainers.

  • Freely chosen keywords characterizing the package.

    keywords = ["jupyter", "kernel", "matlab"]
  • Classifiers characterizing the project, from a defined list.

    classifiers = [
    "Development Status :: 5 - Production/Stable",
    "Framework :: Jupyter",
    "Intended Audience :: Science/Research",
    "Intended Audience :: Developers",
    "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
    "Programming Language :: Python :: 3",
    "Topic :: Scientific/Engineering"
    ]
  • Packages this package depends on, specified according to PEP 508.

    dependencies = [
        "ipykernel",
        "matlabengine",
        "wurlitzer"
    ]
  • URLs where further information can be found, as a sub-table. Normally Homepage is sufficient, but separate entries for Documentation, Repository, and Changelog are also supported.

    [project.urls]
    Homepage = "https://github.com/allefeld/mkernel"

In addition it is possible

Additional features depending on a build backend

We here use hatchling.build, which has to be configured via the build-system table:

requires = ["hatchling"]
build-backend = "hatchling.build"
  • Version information can be obtained from the implementation files. To do so, replace version = "1.0.0" by

    dynamic = ["version"]

    and add

    [tool.hatch.version]
    path = "src/mkernel/kernel.py"

    where the specified file has to contain a line of the form __version__ = '1.0.0'.

  • Non-implementation files (wheel subdirectory {distribution}-{version}.data/) can be included in the package, e.g. a Jupyter kernel specification.

    [tool.hatch.build.targets.wheel.shared-data]
    "kernelspec/kernel.json" = "share/jupyter/kernels/mkernel/kernel.json"

    The entries of this table map paths within the project directory to paths within {distribution}-{version}.data/data/, i.e. the data files part of the install scheme.

See also OS Integration Files in Python Packages.

Building

The simplest way to build the package into a wheel file is to run from the project directory:

pip wheel --no-deps .

It is also implicitly built when installing from source (either a local directory or a git repository).

How to create a package for conda

TODO

Conda package specification

Building conda packages with conda skeleton